package raft

import (
	"6.824/utils"
)

type smcandidate struct {
	rf *Raft
}

func (candidate *smcandidate) enter(oldstate State, isnewterm bool) {
	utils.Assert(candidate.rf.persistentContext.VotedFor == -1)
	candidate.rf.WriteVoted(candidate.rf.me)
	candidate.startElection()

}

func (candidate *smcandidate) startElection() {
	rf := candidate.rf
	rf.Log("INFO", "begin election, lastlogindex: %d lastlogterm:%v", rf.persistentContext.GetLastIndex(), rf.getLastLogTerm())
	curTerm := rf.persistentContext.CurrentTerm
	lstterm := rf.getLastLogTerm()
	lstindex := rf.persistentContext.GetLastIndex()
	grantedcnt := 0

	for i := 0; i < len(rf.peers); i++ {
		if i == rf.me {
			continue
		}
		go func(i int) {
			reply := RequestVoteReply{}
			ok := rf.sendRequestVote(i, &RequestVoteArgs{curTerm, rf.me, lstindex, lstterm}, &reply)
			if !ok {
				return
			}
			rf.begin()
			defer rf.end()

			if rf.handleOthersTerm(reply.Term) || rf.killed() {
				return
			}

			if rf.persistentContext.CurrentTerm != curTerm || rf.currentState != CandidateState {
				return
			}
			if reply.VoteGranted {
				grantedcnt++
				if grantedcnt >= len(rf.peers)/2 {
					rf.changeToState(LeaderState, curTerm)
				}
			}

		}(i)
	}

}
